/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = msmq_analysis.c                                               */
/*  NOTE      = MSMQ协议解析                                                  */
/*  DATE      = 2015/08/13 by wuwk                                            */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <libxml/xpath.h>
#include <libxml/parser.h>
#include <unistd.h>
#include <netinet/in.h>

#include "msmq_core.h"
#include "msmq_comm.h"
#include "iconv2utf8.h"
#include "frsoap_parse.h"
#include "msmq_analysis.h"

#define MSMQ_BINARY_BOOLEAN             0x01
#define MSMQ_BINARY_CHAR                0x03
#define MSMQ_BINARY_SHORT               0x07
#define MSMQ_BINARY_INT                 0x08
#define MSMQ_BINARY_LONG                0x09
#define MSMQ_BINARY_FLOAT               0x0b
#define MSMQ_BINARY_DOUBLE              0x06

#define MSMQ_ACTIVEX_CHAR               0x12
#define MSMQ_ACTIVEX_STRING             0x1f
#define MSMQ_ACTIVEX_SHORT              0x02
#define MSMQ_ACTIVEX_INT                0x03
#define MSMQ_ACTIVEX_FLOAT              0x04
#define MSMQ_ACTIVEX_DOUBLE             0x05
#define MSMQ_ACTIVEX_LONG               0x14
#define MSMQ_ACTIVEX_BOOLEAN            0x0b

#define MSMQ_MESSAGE_MAXLEN           16*1048576

#define MSMQ_METHOD_PUT                 "PUT"
#define MSMQ_METHOD_GET                 "GET"

#define MSMQ_BROADCAST                  "MULTICAST"

#define MSMQ_METHOD_PUT_FLAG            1
#define MSMQ_METHOD_GET_FLAG            2

#define MQ_PUB                          APM_REPORT_KEY_PUB".mq"
#define MQ_PUB_QUE                      MQ_PUB".queue"
#define MQ_PUB_MSG                      MQ_PUB".message"

#define MQ_NOTIFY                       APM_REPORT_KEY_NOTIFY".mq"
#define MQ_NOTIFY_TOPIC                   MQ_NOTIFY".topic"
//#define MQ_NOTIFY_MSG                   MQ_NOTIFY".message"

#define MQ_REQUEST_TOPIC              "request.mq.topic"
#define MQ_REQUEST_QUEUE              "request.mq.queue"

#define MQ_MSG_TYPE             "mq.message.type"

#define MQ_MSG_TYPE_TEXT             "text"
#define MQ_MESSAGE_SIZE          "mq.message.size"

typedef struct __st_msmq_content {
    int i_len;
    char *p_data;
} Msmq_content;


FR_STATIC int __is_dcerpc(Frbyte_Packet *p_st_data)
{
    char arr_tmp[4];
    memset(arr_tmp, 0x00, sizeof(arr_tmp));

    if (p_st_data == NULL)
        return 0;

    if (bytebuff_peek_bytes(p_st_data, arr_tmp, 3) == FR_FAIL)
        return 0;

    if (arr_tmp[0] != 5)
        return 0;

    if (arr_tmp[1] != 0 && arr_tmp[1] != 1)
        return 0;

    if (arr_tmp[2] > 20)
        return 0;

    return 1;
}

/*******************************************************************************
*  FUNC     :  长度和数据解析
*  ARGS     :  p_st_data (数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_skip_content(Frbyte_Packet *p_st_data)
{
    char arr_len[2];
    int i_len = 0;
    int i_ret = 0;

    if (p_st_data == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 1)
        return FR_FAIL;
    /* 取长度 */
    i_ret = bytebuff_get_bytes(p_st_data, arr_len, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    i_len = *arr_len;
    if (bytebuff_remaining(p_st_data) < i_len)
        return FR_FAIL;
    bytebuff_skip(p_st_data, i_len);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  XML数据解析
*  ARGS     :  p_data(xml数据)
            :  p_st_body_data(上报链表)
            :  p_key(key)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
//FR_STATIC int __msmq_analysis_xml_data(char *p_data
//                                     , Frreport_body_data *p_st_body_data
//                                     , char *p_key)
//{
//    xmlDocPtr p_st_doc = NULL;
//    xmlNodePtr p_st_root = NULL;
//    xmlNodePtr p_st_current = NULL;
//    xmlChar *p_content = NULL;
//    char arr_key[64];
//    char *p_value = NULL;
//
//    if (p_data == NULL)
//        return FR_FAIL;
//
//    if (*p_data == '\0')
//        return FR_SUCC;
//
//    p_st_doc = xmlReadMemory(p_data, strlen(p_data), NULL, "UTF8", XML_PARSE_NOBLANKS);
//    if (p_st_doc == NULL)
//        return FR_FAIL;
//
//    /* 根节点 */
//    p_st_root = xmlDocGetRootElement(p_st_doc);
//    if (p_st_root == NULL)
//        goto err;
//
//    if (xmlStrcmp(p_st_root->name, (const xmlChar *) "MessageObj") == 0)
//        p_st_current = xmlFirstElementChild(p_st_root);
//    else
//        p_st_current = p_st_root;
//
//    for (; p_st_current; p_st_current = p_st_current->next)
//    {
//        /* 内容 */
//        p_content = xmlNodeGetContent(p_st_current);
//        if (p_content == NULL)
//            goto err;
//
//        p_value = frmalloc(strlen((char *)p_content) + 1);
//        if (p_value == NULL)
//            goto err;
//        memset(p_value, 0x00, strlen((char *)p_content) + 1);
//
//        strncpy(p_value, (char *)p_content, strlen((char *)p_content));
//
//        if (strncmp(p_key, MQ_NOTIFY, strlen(p_key)) == 0)
//            snprintf(arr_key, sizeof(arr_key), "%s.message.%s", p_key, (const char *)p_st_current->name);
//        else
//            snprintf(arr_key, sizeof(arr_key), "%smessage.%s", p_key, (const char *)p_st_current->name);
//
//        /* key-value上报 */
//        if (FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, arr_key, p_value) == FR_FAIL)
//        {
//            frfree(p_value);
//            goto err;
//        }
//
//        frfree(p_value);
//        xmlFree(p_content);
//    }
//
//    xmlFreeDoc(p_st_doc);
//    return FR_SUCC;
//
//err:
//    xmlFreeDoc(p_st_doc);
//    if (p_content)
//        xmlFree(p_content);
//    return FR_FAIL;
//}

/*******************************************************************************
*  FUNC     :  activex字符串消息取得
*  ARGS     :  p_st_body_data(上报链表)
            :  p_st_data(数据)
            :  p_key(上报key)
            : u32_data_len(数据长度)
            : i_endian(unicode大头/小头)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_get_activex_string(Frreport_body_data *p_st_body_data
                                    , Frbyte_Packet *p_st_data
                                    , char *p_key
                                    , uint32_t u32_data_len
                                    , LITTLE_BIG_ENDIAN i_endian)
{
    char *p_data = NULL;
    char *p_data_utf8 = NULL;
    unsigned int ui_data_utf8_len = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || u32_data_len == 0)
        return FR_FAIL;

    p_data = (char *)frmalloc(u32_data_len + 1);
    if (p_data == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < (int)u32_data_len)
        return FR_FAIL;
    i_ret = bytebuff_get_bytes(p_st_data, p_data, u32_data_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_data);
        return FR_FAIL;
    }

    if (i_endian == BYTE_LITTLE_ENDIAN)
        i_ret = iconv_to_utf8(p_data, u32_data_len, (char *)"UNICODE", &p_data_utf8, &ui_data_utf8_len);
    else
        i_ret = iconv_to_utf8(p_data, u32_data_len, (char *)"UNICODEBIG", &p_data_utf8, &ui_data_utf8_len);

    frfree(p_data);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* utf8数据上报 */
    i_ret = FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, p_key, p_data_utf8);
    frfree(p_data_utf8);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  binary格式解析
*  ARGS     :  p_st_body_data(上报链表)
            :  p_st_data(数据)
            :  p_report_pre(请求/响应前缀)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_binary(Frreport_body_data *p_st_body_data
                                   , Frbyte_Packet *p_st_data
                                   , char *p_report_pre)
{
    Msmq_content st_content;
    uint32_t u32_data_len = 0;
    char arr_msgtype[64];
    char arr_tmp[2];
    int i_ret = 0;

    if (p_st_data == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 10)
        return FR_FAIL;

    /* 消息长度 */
    bytebuff_skip(p_st_data, 6);
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_data_len, BYTE_LITTLE_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 消息最大长度4M */
    if (u32_data_len > MSMQ_MESSAGE_MAXLEN)
    {
        frdbg("length of msmq message over.\n");
        return FR_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < 38 + 4)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 37);
    memset(arr_tmp, 0x00, sizeof(arr_tmp));
    i_ret = bytebuff_get_bytes(p_st_data, arr_tmp, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 4);

    snprintf(arr_msgtype, sizeof(arr_msgtype), "%s%s.1", p_report_pre, MQ_MSG_TYPE);
    /* message.type上报 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, arr_msgtype, MQ_MSG_TYPE_TEXT);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    memset(&st_content, 0x00, sizeof(st_content));
    if (*arr_tmp == '\x06')
    {
        /* string型,从长度位开始的长度 */
        i_ret = msmq_get_string(p_st_body_data, p_st_data, u32_data_len - 23, p_report_pre);
        return i_ret;
    }

    /* 其他类型 */
    /* System.xxx */
    i_ret = __msmq_analysis_skip_content(p_st_data);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 4)
        return FR_FAIL;
    bytebuff_skip(p_st_data, 4);
    /* m_value */
    i_ret = __msmq_analysis_skip_content(p_st_data);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 2)
        return FR_FAIL;
    bytebuff_skip(p_st_data, 1);

    i_ret = bytebuff_get_bytes(p_st_data, arr_tmp, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;
    arr_tmp[1] = '\0';

    switch (*arr_tmp)
    {
        case MSMQ_BINARY_CHAR:
            i_ret = msmq_get_char(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case MSMQ_BINARY_SHORT:
            i_ret = msmq_get_short(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case MSMQ_BINARY_INT:
            i_ret = msmq_get_int(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case MSMQ_BINARY_LONG:
            i_ret = msmq_get_long(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case MSMQ_BINARY_FLOAT:
            i_ret = msmq_get_float(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case MSMQ_BINARY_DOUBLE:
            i_ret = msmq_get_double(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case MSMQ_BINARY_BOOLEAN:
            i_ret = msmq_get_boolean(p_st_body_data, p_st_data, p_report_pre);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        default:
            return FR_SUCC;
    }

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  activex格式解析
*  ARGS     :  p_st_body_data(上报链表)
            :  p_st_data(数据)
            :  p_report_pre(请求/响应前缀)
            :  p_type(数据类型)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_activex(Frreport_body_data *p_st_body_data
                                    , Frbyte_Packet *p_st_data
                                    , char *p_report_pre
                                    , char *p_type)
{
    uint32_t u32_data_len = 0;
    char arr_key[64];
    char arr_msgtype[64];
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_data == NULL)
        return FR_FAIL;

    /* 消息长度 */
    bytebuff_skip(p_st_data, 6);
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_data_len, BYTE_LITTLE_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (u32_data_len == 0)
        return FR_FAIL;

    /* 消息最大长度16M */
    if (u32_data_len > MSMQ_MESSAGE_MAXLEN)
    {
        frdbg("length of msmq message over.\n");
        return FR_FAIL;
    }

    snprintf(arr_msgtype, sizeof(arr_msgtype), "%s%s.1", p_report_pre, MQ_MSG_TYPE);
    /* message.type上报 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, arr_msgtype, MQ_MSG_TYPE_TEXT);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 数据 */
    bytebuff_skip(p_st_data, 20);
    if (*p_type == MSMQ_ACTIVEX_CHAR || *p_type == MSMQ_ACTIVEX_STRING
        || *p_type == 0)
    {
        snprintf(arr_key, sizeof(arr_key), "%s%smessage.text.1", p_report_pre, MSMQ_REPORT_KEY);

        if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\xff\xfe", 2, &i_idx) != FR_FAIL)
        {
            bytebuff_setPosition(p_st_data, i_idx+2);
            u32_data_len -= 2;
            i_ret = __msmq_get_activex_string(p_st_body_data, p_st_data, arr_key, u32_data_len, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
        }
        else if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\xfe\xff", 2, &i_idx) != FR_FAIL)
        {
            bytebuff_setPosition(p_st_data, i_idx+2);
            u32_data_len -= 2;
            i_ret = __msmq_get_activex_string(p_st_body_data, p_st_data, arr_key, u32_data_len, BYTE_BIG_ENDIAN);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
        }
        else
        {
            i_ret = __msmq_get_activex_string(p_st_body_data, p_st_data, arr_key, u32_data_len, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
        }
    }
    else
    {
        switch (*p_type)
        {
            case MSMQ_ACTIVEX_SHORT:
                i_ret = msmq_get_short(p_st_body_data, p_st_data, p_report_pre);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
                break;
            case MSMQ_ACTIVEX_INT:
                i_ret = msmq_get_short(p_st_body_data, p_st_data, p_report_pre);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
                break;
            case MSMQ_ACTIVEX_FLOAT:
                i_ret = msmq_get_float(p_st_body_data, p_st_data, p_report_pre);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
                break;
            case MSMQ_ACTIVEX_DOUBLE:
                i_ret = msmq_get_double(p_st_body_data, p_st_data, p_report_pre);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
                break;
            case MSMQ_ACTIVEX_LONG:
                i_ret = msmq_get_long(p_st_body_data, p_st_data, p_report_pre);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
                break;
            case MSMQ_ACTIVEX_BOOLEAN:
                i_ret = msmq_get_boolean(p_st_body_data, p_st_data, p_report_pre);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
                break;
            default:
                return FR_SUCC;
        }
    }

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  xml格式解析
*  ARGS     :  p_st_body_data(上报链表)
            :  p_st_data(数据)
            :  p_report_pre(请求/响应前缀)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_xml(Frreport_body_data *p_st_body_data
                                , Frbyte_Packet *p_st_data
                                , char *p_report_pre
                                , char *p_activex_type)
{
    char *p_value = NULL;
    char arr_key[64];
    char arr_msgtype[64];
    uint32_t u32_data_len = 0;
    unsigned int ui_pos = 0;
    unsigned int ui_pos_start = 0;
    int i_label = 0;
    int i_ret = 0;

    if (p_st_data == NULL)
        return FR_FAIL;

    ui_pos_start = bytebuff_getPosition(p_st_data);

    if (bytebuff_remaining(p_st_data) < 10)
        return FR_FAIL;
    /* 消息长度 */
    bytebuff_skip(p_st_data, 6);
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_data_len, BYTE_LITTLE_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 消息最大长度16M */
    if (u32_data_len > MSMQ_MESSAGE_MAXLEN)
    {
        frdbg("length of msmq message over.\n");
        return FR_FAIL;
    }
    else if (u32_data_len == 0)
        return FR_FAIL;

    snprintf(arr_msgtype, sizeof(arr_msgtype), "%s%s.1", p_report_pre, MQ_MSG_TYPE);
    /* message.type上报 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, arr_msgtype, MQ_MSG_TYPE_TEXT);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    ui_pos = p_st_data->ui_all_len - p_st_data->ui_remaining;
    /* 找到<?xml */
    i_ret = bytebuff_memstr(p_st_data, ui_pos, bytebuff_length(p_st_data), "<?xml", 5, &i_label);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    bytebuff_setPosition(p_st_data, i_label);

    p_value = (char *)frmalloc(u32_data_len + 1);
    if (p_value == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < (int)u32_data_len)
        return FR_FAIL;
    i_ret = bytebuff_get_bytes(p_st_data, p_value, u32_data_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_value);
        return FR_FAIL;
    }
    p_value[u32_data_len] = '\0';

    /* 不符合xml格式 */
    if (frxml_detect(p_value, u32_data_len) != FR_SUCC)
    {
        frfree(p_value);
        bytebuff_setPosition(p_st_data, ui_pos_start);
        i_ret = __msmq_analysis_activex(p_st_body_data, p_st_data, p_report_pre, p_activex_type);
        return i_ret;
    }

    snprintf(arr_key, sizeof(arr_key), "%s%smessage.text.1", p_report_pre, MSMQ_REPORT_KEY);

    /* xml数据完整上报 */
    if (frreport_body_l7_add_str(p_st_body_data, arr_key, p_value) == FR_FAIL)
    {
        frfree(p_value);
        return FR_FAIL;
    }
    frfree(p_value);

    /* 解析XML数据 */
//    i_ret = __msmq_analysis_xml_data(p_value, p_st_body_data, arr_key);
//    frfree(p_value);
//    if (i_ret == FR_FAIL)
//        return FR_FAIL;

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  Direct解析(目的IP和队列名)
*  ARGS     :  p_st_private (MSMQ的私有信息)
            :  p_st_body_data(上报链表)
            :  p_st_session(msmq的session数据)
            :  p_st_data(数据)
            :  p_report_pre(请求/响应前缀)
            :  u16_direct_len(direct的长度)
            :  i_method_flag(消息类型 PUT/GET)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_direct(L7session_msmq_private *p_st_private
                                   , Frreport_body_data *p_st_body_data
                                   , Msmq_L7session *p_st_session
                                   , Frbyte_Packet *p_st_data
                                   , char *p_report_pre
                                   , uint16_t u16_direct_len
                                   , int i_method_flag)
{
    char *p_direct = NULL;
    char *p_direct_utf8 = NULL;
    char *p_queue = NULL;
    char *p_broadcast = NULL;
//    char arr_key[64];
    char arr_title[64];
    unsigned int ui_direct_utf8_len = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_session == NULL || p_st_data == NULL || p_report_pre == NULL)
        return FR_FAIL;

    p_direct = (char *)frmalloc(u16_direct_len + 1);
    if (p_direct == NULL)
        return FR_FAIL;

    /* 取direct数据 */
    i_ret = bytebuff_get_bytes(p_st_data, p_direct, u16_direct_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_direct);
        return FR_FAIL;
    }
    p_direct[u16_direct_len] = '\0';

    /* 数据转换成UTF-8 */
    i_ret = iconv_to_utf8(p_direct, u16_direct_len, (char *)"UNICODE", &p_direct_utf8, &ui_direct_utf8_len);
    frfree(p_direct);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 队列名 */
    p_queue = strrchr(p_direct_utf8, '\\');
    if (p_queue == NULL || strlen(p_queue) < 2)
    {
        frfree(p_direct_utf8);
        return FR_FAIL;
    }

    p_queue += 1;

    /* 多播判断 */
    if (strncmp(p_queue, MSMQ_BROADCAST, strlen(MSMQ_BROADCAST)) == 0)
    {
        p_broadcast = strchr(p_queue, '=');
        if (p_broadcast == NULL)
        {
            frfree(p_direct_utf8);
            return FR_FAIL;
        }
        p_broadcast++;

        /* 添加title */
        if (i_method_flag == MSMQ_METHOD_PUT_FLAG)
        {
            snprintf(arr_title, sizeof(arr_title), "PUB %s", p_broadcast);

            /* request.mq.topic上报 */
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_REQUEST_TOPIC, p_broadcast);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
        }
        else if (i_method_flag == MSMQ_METHOD_GET_FLAG)
        {
            snprintf(arr_title, sizeof(arr_title), "NOTIFY %s", p_broadcast);

            /* notify.mq.topic上报 */
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_NOTIFY_TOPIC, p_broadcast);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
        }
        else
        {
            frfree(p_direct_utf8);
            return FR_SUCC;
        }

        /* 多播地址作为title */
        if (p_st_session->p_title == NULL)
        {
            p_st_session->p_title = frstrdup(arr_title);
            if (p_st_session->p_title == NULL)
            {
                frfree(p_direct_utf8);
                return FR_FAIL;
            }
        }

        /* publish的queue */
        i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_PUB_QUE, p_broadcast);
        if (i_ret == FR_FAIL)
        {
            frfree(p_direct_utf8);
            return FR_FAIL;
        }
        p_st_private->i_msg_type = MSMQ_MSG_TYPE_PUB;
        p_queue = p_broadcast;
    }
    else
    {
        /* 添加title */
        if (i_method_flag == MSMQ_METHOD_PUT_FLAG)
        {
            snprintf(arr_title, sizeof(arr_title), "PUT %s", p_queue);

            /* request.mq.queue上报 */
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_REQUEST_QUEUE, p_queue);
            if (i_ret == FR_FAIL)
            {
                frfree(p_direct_utf8);
                return FR_FAIL;
            }
        }
        else if (i_method_flag == MSMQ_METHOD_GET_FLAG)
            snprintf(arr_title, sizeof(arr_title), "GET %s", p_queue);
        else
        {
            frfree(p_direct_utf8);
            return FR_SUCC;
        }

//        snprintf(arr_key, sizeof(arr_key), "%smq.queue", p_report_pre);
//        i_ret = frreport_body_l7_add_str(p_st_body_data, arr_key, p_queue);
//        if (i_ret == FR_FAIL)
//        {
//            frfree(p_direct_utf8);
//            return FR_FAIL;
//        }

        /* 设置title */
        if (p_st_session->p_title == NULL)
        {
            p_st_session->p_title = frstrdup(arr_title);
            if (p_st_session->p_title == NULL)
            {
                frfree(p_direct_utf8);
                return FR_FAIL;
            }
        }
    }

    if (p_st_session->p_queue_name == NULL)
    {
        p_st_session->p_queue_name = frstrdup(p_queue);
        if (p_st_session->p_queue_name == NULL)
        {
            frfree(p_direct_utf8);
            return FR_FAIL;
        }
    }
    frfree(p_direct_utf8);

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  消息解析
*  ARGS     :  p_st_private(msmq私有数据)
            :  p_st_body_data(上报链表)
            :  p_st_data(数据)
            :  p_report_pre(请求/响应前缀)
            :  i_method_flag(消息类型 PUT/GET)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_msg(L7session_msmq_private *p_st_private
                                , Frreport_body_data *p_st_body_data
                                , Frbyte_Packet *p_st_data
                                , char *p_report_pre
                                , int i_method_flag
                                , int *i_need_report)
{
    char arr_tmp[2];
    char arr_activex_type[2];
    char arr_method[64];
    char arr_size[64];
    unsigned int ui_pos = 0;
    int i_label = 0;
    int i_index = 0;
    int i_remove = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    ui_pos = p_st_data->ui_all_len - p_st_data->ui_remaining;
    /* 没找到则认为是事务性消息的响应, 不解析 */
    if (bytebuff_memstr(p_st_data, ui_pos, bytebuff_length(p_st_data), "\x0e\x80", 2, &i_index) == FR_FAIL)
    {
        if (strncmp(p_report_pre, "response", 8) == 0 && p_st_private->i_need_resp == MSMQ_YES)
            *i_need_report = MSMQ_YES;
        else
            *i_need_report = MSMQ_NO;
        return FR_SUCC;
    }

    i_remove = i_index - 20;
    bytebuff_setPosition(p_st_data, i_remove);
    memset(arr_activex_type, 0x00, sizeof(arr_activex_type));
    i_ret = bytebuff_get_bytes(p_st_data, arr_activex_type, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    memset(arr_tmp, 0x00, sizeof(arr_tmp));
    i_ret = bytebuff_get_bytes(p_st_data, arr_tmp, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    snprintf(arr_method, sizeof(arr_method), "%smq.method", p_report_pre);
    if (i_method_flag == MSMQ_METHOD_GET_FLAG)
    {
        /* 消息类型 */
        i_ret = frreport_body_l7_add_str(p_st_body_data, arr_method, MSMQ_METHOD_GET);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }
    else
    {
        /* 消息类型 */
        i_ret = frreport_body_l7_add_str(p_st_body_data, arr_method, MSMQ_METHOD_PUT);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    ui_pos = p_st_data->ui_all_len - p_st_data->ui_remaining;

    if (*arr_tmp == '\x03')
        i_ret = __msmq_analysis_binary(p_st_body_data, p_st_data, p_report_pre);
    else if (bytebuff_memstr(p_st_data, ui_pos, bytebuff_length(p_st_data), "<?xml version=", 14, &i_label) == FR_SUCC)
        i_ret = __msmq_analysis_xml(p_st_body_data, p_st_data, p_report_pre, arr_activex_type);
    else
        i_ret = __msmq_analysis_activex(p_st_body_data, p_st_data, p_report_pre, arr_activex_type);
    if (i_ret != FR_SUCC)
        return i_ret;

    if (strncmp(p_report_pre, "response", 8) == 0)
    {
        snprintf(arr_size, sizeof(arr_size), "response.%s", MQ_MESSAGE_SIZE);
        // 消息个数上报
        i_ret = frreport_body_l7_add_int(p_st_body_data, arr_size, 1);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }


    return i_ret;
}

/*******************************************************************************
*  FUNC     :  取soap消息优先级上报
*  ARGS     :  p_st_body_data(上报链表)
            :  p_st_data(数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_get_priority(Frreport_body_data *p_st_body_data
                                                      , Frbyte_Packet *p_st_data)
{
    char arr_priority[2];
    char arr_key[64];
    int i_index = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), bytebuff_length(p_st_data), "<Priority>", 10, &i_index);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 取优先级 */
    memset(arr_priority, 0x00, sizeof(arr_priority));
    i_ret = bytebuff_get_bytes_at(p_st_data, i_index+10, 1, arr_priority);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 判断消息优先级是否合法 */
    if (msmq_check_msg_priority(atoi(arr_priority)) != MSMQ_TRUE)
        return FR_FAIL;

    /* 消息优先级上报 */
    memset(arr_key, 0x00, sizeof(arr_key));
    strcpy(arr_key, "notify.mq.priority.1");
    i_ret = frreport_body_l7_add_int(p_st_body_data, arr_key, atoi(arr_priority));
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}


/*******************************************************************************
*  FUNC     :  多播消息解析
*  ARGS     :  p_st_private(MSMQ的私有数据)
            :  p_st_body_data(上报链表)
            :  p_st_data(数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_analysis_notify(L7session_msmq_private *p_st_private
                                   , Frreport_body_data *p_st_body_data
                                   , Frbyte_Packet *p_st_data)
{
    Msmq_L7session *p_st_session = NULL;
    char arr_tmp[64];
    char arr_title[64];
    char arr_key[64];
    char arr_msgtype[64];
    char arr_size[64];
    char *p_xml_data = NULL;
    uint32_t u32_envelope_len = 0;
    uint32_t u32_describe_len = 0;
    uint32_t u32_data_len = 0;
    unsigned int ui_offset = 0;
    int i_space1 = 0;
    int i_space2 = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_l7_session == NULL
        || p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_l7_session;

    if (bytebuff_remaining(p_st_data) < 176 + 4)
        return FR_FAIL;

    /* 到信封长度 */
    bytebuff_skip(p_st_data, 176);
    /* 信封长度 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_envelope_len, BYTE_LITTLE_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    u32_envelope_len = u32_envelope_len*2;
    if (bytebuff_remaining(p_st_data) < (int)u32_envelope_len)
        return FR_FAIL;
    bytebuff_skip(p_st_data, u32_envelope_len);

    if (bytebuff_remaining(p_st_data) < 14)
        return FR_FAIL;
    /* 到消息长度 */
    bytebuff_skip(p_st_data, 10);
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_data_len, BYTE_LITTLE_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (u32_data_len == 0)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 4)
        return FR_FAIL;
    /* 消息描述长度 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_describe_len, BYTE_LITTLE_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 取多播地址和端口 */
    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), bytebuff_length(p_st_data), " ", 1, &i_space1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    ui_offset = i_space1+1-bytebuff_getPosition(p_st_data);
    bytebuff_setPosition(p_st_data, i_space1+1);

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), bytebuff_length(p_st_data), " ", 1, &i_space2);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    memset(arr_tmp, 0x00, sizeof(arr_tmp));
    ui_offset += (i_space2-bytebuff_getPosition(p_st_data));
    if (bytebuff_remaining(p_st_data) < i_space2-bytebuff_getPosition(p_st_data))
        return FR_FAIL;

    if (i_space2-bytebuff_getPosition(p_st_data) >= (int)sizeof(arr_tmp))
        return FR_FAIL;
    i_ret = bytebuff_get_bytes(p_st_data, arr_tmp, i_space2-bytebuff_getPosition(p_st_data));
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 多播地址 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_NOTIFY_TOPIC, arr_tmp);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_l7_session;

    snprintf(arr_title, sizeof(arr_title), "NOTIFY %s", arr_tmp);

    /* 多播地址作为title */
    if (p_st_session->p_title == NULL)
    {
        p_st_session->p_title = frstrdup(arr_title);
        if (p_st_session->p_title == NULL)
            return FR_FAIL;
    }

    snprintf(arr_key, sizeof(arr_key), "%s.method", MQ_NOTIFY);
    i_ret = frreport_body_l7_add_str(p_st_body_data, arr_key, MSMQ_METHOD_GET);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 添加session的queue */
    if (p_st_session->p_queue_name == NULL)
    {
        p_st_session->p_queue_name = frstrdup(arr_tmp);
        if (p_st_session->p_queue_name == NULL)
            return FR_FAIL;
    }

    /* 取soap消息优先级上报 */
    i_ret = __msmq_get_priority(p_st_body_data, p_st_data);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    snprintf(arr_msgtype, sizeof(arr_msgtype), "%s.%s.1", APM_REPORT_KEY_NOTIFY, MQ_MSG_TYPE);
    /* message.type上报 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, arr_msgtype, MQ_MSG_TYPE_TEXT);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < int(u32_describe_len - ui_offset))
        return FR_FAIL;
    /* 跳过消息描述 */
    bytebuff_skip(p_st_data, u32_describe_len - ui_offset);

    p_xml_data = (char *)frmalloc(u32_data_len + 1);
    if (p_xml_data == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < (int)u32_data_len)
        return FR_FAIL;
    /* 取消息 */
    i_ret = bytebuff_get_bytes(p_st_data, p_xml_data, u32_data_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_xml_data);
        return FR_FAIL;
    }

    p_xml_data[u32_data_len] = '\0';

    snprintf(arr_key, sizeof(arr_key), "%s.message.text.1", MQ_NOTIFY);

    if (FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, arr_key, p_xml_data) == FR_FAIL)
    {
        frfree(p_xml_data);
        return FR_FAIL;
    }
    frfree(p_xml_data);

    snprintf(arr_size, sizeof(arr_size), "notify.%s", MQ_MESSAGE_SIZE);
    // 消息个数上报
    i_ret = frreport_body_l7_add_int(p_st_body_data, arr_size, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_st_private->i_msg_type = MSMQ_MSG_TYPE_NOTIFY;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  MSMQ数据解析
*  ARGS     :  p_st_private (MSMQ的私有信息)
            :  p_st_body_data(上报链表)
            :  i_req_resp(请求/响应)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int msmq_analysis_data(L7session_msmq_private *p_st_private
                     , Frreport_body_data *p_st_body_data
                     , int i_req_resp
                     , int *i_need_report)
{
    Frbyte_Packet *p_st_data = NULL;
    Msmq_L7session *p_st_session = NULL;
    char arr_tmp[2];
    char arr_type[64];
    char arr_priority[64];
    int i_lior_index = 0;
    int i_method_flag = 0;
    uint32_t u32_data_len = 0;
    uint32_t u32_priority = 0;
    uint32_t u32_msglen = 0;
    uint16_t u16_direct_len = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_l7_session == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    *i_need_report = MSMQ_NO;

    p_st_session = p_st_private->p_st_l7_session;

    if (p_st_session->p_server == NULL)
    {
        p_st_session->p_server = frstrdup("MSMQ");
        if (p_st_session->p_server == NULL)
            return FR_FAIL;
    }

    if (i_req_resp == MSMQ_REQUEST)
    {
        if (p_st_private->p_st_req)
            p_st_data = p_st_private->p_st_req->p_st_data_req;
        else
            return FR_FAIL;

        snprintf(arr_type, sizeof(arr_type), "%s.", APM_REPORT_KEY_REQ);
    }
    else
    {
        if (p_st_private->p_st_resp)
            p_st_data = p_st_private->p_st_resp->p_st_data_resp;
        else
            return FR_FAIL;

        snprintf(arr_type, sizeof(arr_type), "%s.", APM_REPORT_KEY_RESP);

        i_ret = frreport_body_l7_add_int(p_st_body_data, "response.code", 0);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    if (__is_dcerpc(p_st_data) == 1 && i_req_resp == MSMQ_REQUEST)
    {
        p_st_private->i_protocol_type = MSMQ_DECRPC;
        *i_need_report = MSMQ_YES;
        return FR_SUCC;
    }

    /* 没有LIOR,不解析消息 */
    i_ret = bytebuff_memstr(p_st_data, 0, bytebuff_length(p_st_data), MSMQ_STR_LIOR, 4, &i_lior_index);
    if (i_ret == FR_FAIL)
        return FR_SUCC;

    if (i_lior_index-bytebuff_getPosition(p_st_data) > 8)
    {
        i_lior_index -= 8;
        bytebuff_skip(p_st_data, i_lior_index);
        /* 取长度 */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_data_len, BYTE_LITTLE_ENDIAN);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    bytebuff_skip(p_st_data, 2);

    memset(arr_tmp, 0x00, sizeof(arr_tmp));
    i_ret = bytebuff_get_bytes(p_st_data, arr_tmp, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;
    u32_priority = *arr_tmp;

    /* 定位到长度 */
    bytebuff_skip(p_st_data, 5);

    u32_msglen = msmq_get_msglen(p_st_data);
    if (u32_msglen == 0)
        return FR_FAIL;

    if (u32_data_len != 0)
    {
        if (i_req_resp == MSMQ_RESPONSE)
            i_method_flag = MSMQ_METHOD_GET_FLAG;
        p_st_private->i_is_get = 1;
    }
    else
    {
        if (i_req_resp == MSMQ_REQUEST)
            i_method_flag = MSMQ_METHOD_PUT_FLAG;
    }

    /* 消息优先级 */
    if (msmq_check_msg_priority(u32_priority) != MSMQ_TRUE)
    {
        if (i_method_flag == MSMQ_METHOD_GET_FLAG)
        {
            i_ret = __msmq_analysis_notify(p_st_private, p_st_body_data, p_st_data);
            *i_need_report = MSMQ_YES;
            return i_ret;
        }
        /* 该response的request有数据且要上报 */
        if (p_st_private->i_need_resp == MSMQ_YES && i_req_resp == MSMQ_RESPONSE)
            *i_need_report = MSMQ_YES;

        return FR_SUCC;
    }

    if (u32_data_len != 0)
    {
        /* 长度不一致,不解析消息 */
        if (u32_data_len != u32_msglen)
            return FR_SUCC;
    }

    if (u32_msglen < 52)
        return FR_SUCC;

    if (i_req_resp == MSMQ_REQUEST)
        p_st_private->p_st_req->i_responserequired = 0;

    /* 消息数据 */
    bytebuff_skip(p_st_data, 52);
    /* 取direct长度 */
    if (bytebuff_get_short(p_st_data, 2, &u16_direct_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    if (u16_direct_len == 0)
        return FR_SUCC;

    /* 服务器信息(IP和队列名) */
    i_ret = __msmq_analysis_direct(p_st_private, p_st_body_data, p_st_session, p_st_data, arr_type, u16_direct_len, i_method_flag);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (p_st_private->i_msg_type == MSMQ_MSG_TYPE_PUB)
        snprintf(arr_type, sizeof(arr_type), "%s.", APM_REPORT_KEY_PUB);

    /* 消息优先级 */
    snprintf(arr_priority, sizeof(arr_priority), "%smq.priority.1", arr_type);
    i_ret = frreport_body_l7_add_int(p_st_body_data, arr_priority, u32_priority);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    *i_need_report = MSMQ_YES;
    /* 消息内容 */
    i_ret = __msmq_analysis_msg(p_st_private, p_st_body_data, p_st_data, arr_type, i_method_flag, i_need_report);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (i_req_resp == MSMQ_REQUEST)
        p_st_private->i_need_resp = MSMQ_YES;

    return FR_SUCC;
}
